<?php

/*
 * Copyright (C) 2009 - 2011 Pham Cong Dinh
 *
 * This file is part of Spica.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
include_once 'library/Swift/lib/swift_required.php';

/**
 * Base class that gives support for SwiftMailer.
 *
 * namespace spica\core\service\MailService
 *
 * @category   spica
 * @package    core
 * @subpackage service
 * @author     Pham Cong Dinh <pcdinh at phpvietnam dot net>
 * @since      Version 0.3
 * @since      May 26, 2009
 * @copyright  Pham Cong Dinh (http://www.phpvietnam.net)
 * @license    http://www.gnu.org/licenses/lgpl-3.0.txt
 * @version    $Id: MailService.php 1869 2011-01-07 18:55:25Z pcdinh $
 */
abstract class SpicaMailService /* implements SpicaGenericService */
{
    /**
     * Indicates mail content is in HTML.
     *
     * @var string
     */
    const CONTENT_HTML = 'text/html';

    /**
     * Indicates mail content is in plain text.
     *
     * @var string
     */
    const CONTENT_TEXT = 'text/plain';

    /**
     * Mail delivery object.
     *
     * @var Swift_Mailer
     */
    public $mailer;

    /**
     * Mail message object.
     *
     * @var Swift_Message
     */
    public $message;

    /**
     * Constructs an object of <code>SpicaMailService</code>
     *
     * @param string $alias
     */
    public function __construct($alias = null)
    {
        $this->init($alias);
    }

    /**
     * Initializes mail service.
     *
     * @param string $alias Configured alias name for a specific mail delivery settings
     */
    public function init($alias)
    {
        $this->message = new Swift_Message();
        $this->mailer  = SpicaMailerFactory::create($alias);
    }

    /**
     * Creates a mail message object.
     *
     * @param  string $subject
     * @param  string $body
     * @param  string $contentType
     * @param  string $charset Defaults to 'UTF-8'
     * @return Swift_Message
     */
    protected function _createMessage($subject = null, $body = null, $contentType = null, $charset = 'UTF-8')
    {
        return new Swift_Message($subject, $body, $contentType, $charset);
    }

    /**
     * Attaches a file to a mail message object.
     *
     * @param string $path Full path to file
     */
    protected function _attachFile($path)
    {
        $this->message->attach(Swift_Attachment::fromPath($path));
    }
}

/**
 * Factory class for generating Swift_Mailer concrete instances from an alias name
 * that represents a subset of configuration entries.
 *
 * namespace spica\core\service\MailerFactory
 *
 * @category   spica
 * @package    core
 * @subpackage service
 * @author     Pham Cong Dinh <pcdinh at phpvietnam dot net>
 * @since      Version 0.3
 * @since      May 27, 2009
 * @copyright  Pham Cong Dinh (http://www.phpvietnam.net)
 * @license    http://www.gnu.org/licenses/lgpl-3.0.txt
 * @version    $Id: MailService.php 1869 2011-01-07 18:55:25Z pcdinh $
 */
class SpicaMailerFactory
{
    /**
     * Sets of mailers.
     *
     * @var array
     */
    protected static $_pool;

    /**
     * Prevents object instantiation.
     */
    protected function __construct() {}

    /**
     * Creates a mail delivery object.
     *
     * @throws InvalidArgumentException when <code>$alias['type']</code> is not supported
     * @param  string $alias
     * @return Swift_Mailer
     */
    public function create($alias)
    {
        if (true === isset(self::$_pool[$alias]) && false === $new)
        {
            return end(self::$_pool[$alias]);
        }

        switch ($alias['type'])
        {
            case 'sendmail':
                $transport = $this->createSendmailTransport(SpicaConfig::getMail($alias));
                break;

            case 'mail':
                $transport = $this->createNativeTransport(SpicaConfig::getMail($alias));
                break;

            case 'smtp':
                $transport = $this->createSendmailTransport(SpicaConfig::getMail($alias));
                break;

            default:
                throw new InvalidArgumentException('Mail transport configuration "'.$alias['type'].'" is not supported. ');
        }

        $mailer = new Swift_Mailer($transport);
        self::$_pool[$alias][] = $mailer;
        return $mailer;
    }

    /**
     * Creates a SMTP-based mail delivery object.
     *
     * @throws InvalidArgumentException when a needed array key in $config is missing
     * @param  array $config
     * @return Swift_SmtpTransport
     */
    public function createSmtpTransport($config)
    {
        if (false === isset($config['host']))
        {
            throw new InvalidArgumentException('Configuration entry "host" must be set when using SMTP to send emails. ');
        }

        if (false === isset($config['port']))
        {
            throw new InvalidArgumentException('Configuration entry "port" must be set when using SMTP to send emails. ');
        }

        $transport = new Swift_SmtpTransport($config['host'], $config['port'], isset($config['security'])?$config['security']:null);

        if (true === isset($config['username']))
        {
            // Mixin is magic
            $transport->setUsername($config['username']);
        }

        if (true === isset($config['password']))
        {
            // Mixin is magic
            $transport->setPassword($config['password']);
        }

        if (false === isset($config['timeout']))
        {
            $transport->setTimeout($config['timeout']);
        }

        // Security protocol: tls or ssl
        if (false === isset($config['protocol']))
        {
            $transport->setEncryption($config['protocol']);
        }

        return $transport;
    }

    /**
     * Creates a mail delivery object using PHP's mail() function.
     *
     * @param  array $config
     * @return Swift_SmtpTransport
     */
    public function createNativeTransport($config)
    {
        if (false === isset($config['param']))
        {
            $config['param'] = '-f%s';
        }

        return new Swift_MailTransport($config['param']);
    }

    /**
     * Creates a Sendmail-based mail delivery object.
     *
     * @param  array $config
     * @return Swift_SmtpTransport
     */
    public function createSendmailTransport($config)
    {
        if (false === isset($config['command']))
        {
            $config['command'] = '/usr/sbin/sendmail -bs';
        }

        return new Swift_SendmailTransport($config['command']);
    }
}

?>